import * as THREE from '../../build/three.module.js';

(async function () {

const load = () => {
  return new Promise(resolve => {
    new THREE.TextureLoader().load('../../textures/2294472375_24a3b8ef46_o.jpg', texture => {
      resolve(texture);
    })
  })
}
const texture = await load();

// 全局变量
let lon = 0, lat = 0, downPointerX = 0, downPointerY = 0, downPointerLon = 0, downPointerLat = 0, count = 0;

// 场景
const scene = new THREE.Scene();

// 相机
const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.z = 200;

// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(devicePixelRatio);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

// 盒子相机
const cubeCamera1 = new THREE.CubeCamera(1, 1000, 256);
cubeCamera1.renderTarget.texture.generateMipmaps = true;
cubeCamera1.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
scene.add(cubeCamera1);

const cubeCamera2 = new THREE.CubeCamera(1, 1000, 256);
cubeCamera2.renderTarget.texture.generateMipmaps = true;
cubeCamera2.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
scene.add(cubeCamera2);

// 材质
const mtl = new THREE.MeshBasicMaterial({ envMap: cubeCamera2.renderTarget.texture });

// 网格对象
const shpere = new THREE.Mesh( new THREE.IcosahedronBufferGeometry(20, 3), mtl );
scene.add(shpere);

const cube = new THREE.Mesh( new THREE.BoxBufferGeometry(20, 20, 20), mtl );
scene.add(cube);

const torus = new THREE.Mesh( new THREE.TorusBufferGeometry(10, 5, 100, 25), mtl );
scene.add(torus);


const options = {
  minFilter: THREE.LinearMipMapLinearFilter,
  magFilter: THREE.LinearFilter,
  generateMipmaps: true
}
scene.background = new THREE.WebGLRenderTargetCube(1024, 1024, options).fromEquirectangularTexture(renderer, texture);

// 渲染函数
const render = () => {

  const time = new Date() * 0.001;

  lon += 0.15;

  lat = Math.max(-85, Math.min(85, lat)); // [-85, 85]取值范围
  const phi = THREE.Math.degToRad(90 - lat);
  const theta = THREE.Math.degToRad(lon);

  // 立方体位置
  cube.position.x = Math.cos(time) * 30;
  cube.position.y = Math.sin(time) * 30;
  cube.position.z = Math.sin(time) * 30;
  cube.rotation.x += 0.03;
  cube.rotation.y += 0.02;

  // 麻花体位置
  torus.position.x = Math.cos(time + 10) * 30;
  torus.position.y = Math.sin(time + 10) * 30;
  torus.position.z = Math.sin(time + 10) * 30;
  torus.rotation.x += 0.03;
  torus.rotation.y += 0.02;

  // 相机自传
  camera.position.x = 100 * Math.sin( phi ) * Math.cos( theta );
  camera.position.y = 100 * Math.cos( phi );
  camera.position.z = 100 * Math.sin( phi ) * Math.sin(theta);
  
  camera.lookAt(scene.position);

  if (count % 2 === 0) {
    cubeCamera1.update(renderer, scene);
    mtl.envMap = cubeCamera1.renderTarget.texture;
  } else {
    cubeCamera2.update(renderer, scene);
    mtl.envMap = cubeCamera2.renderTarget.texture;
  }

  count++;

  renderer.render(scene, camera);
}

// 启动函数
const animate = () => {
  requestAnimationFrame(animate);

  render();
}
animate();

// 事件处理
const handleWindowResize = () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(innerWidth, innerHeight);
}
window.addEventListener('resize', handleWindowResize, false);

// 滚轮事件
const onDocumentMouseWheel = e => {
  const fov = camera.fov + e.deltaY * 0.05;
  
  camera.fov = THREE.Math.clamp(fov, 10, 75);

  camera.updateProjectionMatrix();
}
document.addEventListener('wheel', onDocumentMouseWheel, false);

// 鼠标移动事件
const onDocumentMouseMove = e => {
  lon = ( e.clientX - downPointerX ) * 0.1 + downPointerLon;
  lat = ( e.clientY - downPointerX ) * 0.1 + downPointerLat;
}

// 鼠标抬起事件
const onDocumentMouseUp = () => {
  document.removeEventListener('mousemove', onDocumentMouseMove, false);
  document.removeEventListener('mouseup', onDocumentMouseUp, false);
}

// 鼠标按下事件
const onDocumentMouseDown = e => {
  downPointerX = e.clientX;
  downPointerY = e.clientY;

  downPointerLon = lon;
  downPointerLat = lat;

  document.addEventListener('mousemove', onDocumentMouseMove, false);
  document.addEventListener('mouseup', onDocumentMouseUp, false);
}
document.addEventListener('mousedown', onDocumentMouseDown, false);

})()
